#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <termios.h>
#include <sys/ioctl.h>

#define UART_DEVICE "/dev/ttyCH9344USB0"

void set485Control(int fd, int enable)
{
    ioctl(fd, TIOCMGET, &fd);
    if (enable)
    {
        fd |= TIOCM_RTS;
    }
    else
    {
        fd &= ~TIOCM_RTS;
    }
    ioctl(fd, TIOCMSET, &fd);
}

void set485Send(int fd)
{
    system("./485_4.sh 1");
    set485Control(fd, 1);
}

void set485Receive(int fd)
{
    system("./485_4.sh 0");
    set485Control(fd, 0);
}

int main(int argc, char *argv[])
{
    int fd, ret, fd2;
    struct termios old_cfg = {0}; //用于保存终端配置之前的参数
    struct termios new_cfg = {0}; //用于保存终端新配置的参数
    speed_t speed = B115200;      //定义波特率为115200
    // speed_t speed = B2000000;
    /*第一步，串口初始化*/
    fd = open(UART_DEVICE, O_RDWR | O_NOCTTY | O_NDELAY); //O_NOCTTY 标志，告知系统该节点不会成为进程的控制终端
    if (fd < 0)
    {
        printf("uart device open error\n");
        return -1;
    }

    /*打开485控制设备*/
    fd2 = open(UART_DEVICE, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd2 < 0)
    {
        printf("Open max485_ctl failed\n");
        return -1;
    }

    ret = tcgetattr(fd, &old_cfg);
    if (ret < 0)
    {
        printf("tcgetattr error\n");
        close(fd);
        return -1;
    }

    /*第二步，配置串口参数*/
    cfmakeraw(&new_cfg);        //设置为原始模式
    new_cfg.c_cflag |= CREAD;   // 使能接收
    cfsetspeed(&new_cfg, speed);//将波特率设置为115200
    new_cfg.c_cflag &= ~CSIZE;  //将数据位相关的比特位清零
    new_cfg.c_cflag |= CS8;     //将数据位数设置为8位
    new_cfg.c_cflag &= ~PARENB;
    new_cfg.c_iflag &= ~INPCK;  //设置为无校验模式
    new_cfg.c_cflag &= ~CSTOPB; //将停止位设置为1位
    new_cfg.c_cc[VTIME] = 0;    // 将 MIN 和 TIME 设置为 0
    new_cfg.c_cc[VMIN] = 0;
    ret = tcflush(fd, TCIOFLUSH); //清空缓冲区域
    if (ret < 0)
    {
        printf("tcflush error\n");
        return -1;
    }
    ret = tcsetattr(fd, TCSANOW, &new_cfg); //写入配置、使配置生效
    if (ret < 0)
    {
        printf("tcsetattr error\n");
        return -1;
    }

    set485Receive(fd); // 设置为接收模式

    char buff[100];
    while (1)
    {
        ret = read(fd, buff, sizeof(buff) - 1);
        buff[ret] = 0;
        if (ret < 0)
        {
            printf("read failed\n");
        }
        else if (ret > 0)
        {
            printf("Received message: %s\n", buff);

            // 回复相同的消息
            set485Send(fd); // 设置为发送模式
            write(fd, buff, strlen(buff));
            printf("Echoed back.\n");
            printf("$(date): 485-4 测试成功\n");
            system("echo \"$(date)：485-4 测试成功\" >> /userfs/all.txt");
            set485Receive(fd); // 设置为接收模式
        }
        sleep(1);
    }

    tcsetattr(fd, TCSANOW, &old_cfg); //恢复到之前的配置
    close(fd);
    return 0;
}
